package com.sec.android.app.myfiles.facade.cmd;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.widget.Toast;

import com.sec.android.app.myfiles.R;
import com.sec.android.app.myfiles.activity.FolderSelectorBottomSheetActivity;
import com.sec.android.app.myfiles.facade.MyFilesFacade;
import com.sec.android.app.myfiles.feature.MouseKeyboardMgr;
import com.sec.android.app.myfiles.feature.PrivateModeMgr;
import com.sec.android.app.myfiles.fragment.AbsMyFilesFragment;
import com.sec.android.app.myfiles.info.AppConstants;
import com.sec.android.app.myfiles.info.AppFeatures;
import com.sec.android.app.myfiles.log.Log;
import com.sec.android.app.myfiles.log.SamsungAnalyticsLog;
import com.sec.android.app.myfiles.module.abstraction.FileRecord;
import com.sec.android.app.myfiles.module.abstraction.FileRecord.StorageType;
import com.sec.android.app.myfiles.module.local.foldertree.FolderTreeDbTableInfo;
import com.sec.android.app.myfiles.module.local.foldertree.FolderTreeProviderImp;
import com.sec.android.app.myfiles.navigation.NavigationInfo;
import com.sec.android.app.myfiles.navigation.NavigationInfo.NavigationMode;
import com.sec.android.app.myfiles.navigation.NavigationManager;
import com.sec.android.app.myfiles.operation.FileOperationArgs;
import com.sec.android.app.myfiles.operation.FileOperationFragment;
import com.sec.android.app.myfiles.operation.FileOperationFragment.PostOperation;
import com.sec.android.app.myfiles.operation.FileOperator;
import com.sec.android.app.myfiles.operation.FileOperator.Operation;
import com.sec.android.app.myfiles.provider.DbTableInfo;
import com.sec.android.app.myfiles.util.FileExecute;
import com.sec.android.app.myfiles.util.FileUtils;
import com.sec.android.app.myfiles.util.UiUtils;

import org.puremvc.java.multicore.interfaces.INotification;
import org.puremvc.java.multicore.patterns.command.SimpleCommand;

import java.util.ArrayList;

public class CopyMoveCmd extends SimpleCommand implements PostOperation {
    public enum OperationProgress {
        SELECT_DST,
        DO_OPERATE,
        DOWNLOAD_OPEN,
    }

    private static ArrayList<FileRecord> mSrcRecordList;
    static boolean mRemoveFromPrivateOperation = false;
    private PostOperation mPostOperation;
    private String mDstFullPath;
    private OperationProgress mProgress;
    private Activity mActivity;
    private AbsMyFilesFragment mFragment;

    @Override
    public void execute(INotification notification) {
        Object[] params = (Object[]) notification.getBody();

        Context context = (Context) params[0];
        Operation op = (Operation) params[1];
        mProgress = (OperationProgress) params[2];
        mFragment = (AbsMyFilesFragment) params[3];
        @SuppressWarnings("unchecked")
        ArrayList<FileRecord> srcRecordList = (ArrayList<FileRecord>) params[4];
        FileRecord dstRecord = (FileRecord) params[5];
        mPostOperation = (PostOperation) params[6];

        mActivity = mFragment.getActivity();
        NavigationManager naviMgr = NavigationManager.getInstance(mFragment.getProcessId());
        NavigationInfo curInfo = naviMgr.getCurInfo();
        FileOperationArgs args = new FileOperationArgs();
        args.mProcessId = mFragment.getProcessId();

        switch (mProgress) {
            case SELECT_DST:
                if (AppFeatures.isKnoxDesktopMode() && Operation.COPY.equals(op)) {
                    MouseKeyboardMgr.onCtrlC(mFragment, srcRecordList.get(0));
                } else if (AppFeatures.isKnoxDesktopMode() && Operation.MOVE.equals(op)) {
                    MouseKeyboardMgr.onCtrlX(mFragment, srcRecordList.get(0));
                } else {
                    startDestinationSelectorBottomSheet(op, srcRecordList);
                }
                break;

            case DO_OPERATE:
            case DOWNLOAD_OPEN:
                naviMgr.setFromPrivateStorage(false);
                if (mSrcRecordList == null) {
                    mSrcRecordList = srcRecordList;
                }

                if (curInfo != null && op != Operation.BACKUP) {
                    if (dstRecord == null) {
                        dstRecord = curInfo.getCurRecord();
                        if (curInfo.getNavigationMode() == NavigationMode.Select_move_destination
                                && mSrcRecordList != null && !mSrcRecordList.isEmpty() && !isMovePossible(context, mSrcRecordList.get(0), dstRecord)) {
                            break;
                        }
                        naviMgr.backCurNavigationMode();
                        enterToDst(naviMgr, dstRecord);
                    } else {
                        if (mProgress != OperationProgress.DOWNLOAD_OPEN &&
                                op != Operation.MOVE_TO_PRIVATE &&
                                dstRecord.getStorageType() != StorageType.FolderTree) {
                            enterToDst(naviMgr, dstRecord);
                        }
                    }
                }

                if (dstRecord == null) {
                    Log.e(this, "execute() failed - desRecord is NULL " + mProgress);
                    return;
                }

                if (mProgress == OperationProgress.DOWNLOAD_OPEN) {
                    mDstFullPath = dstRecord.getFullPath();
                    args.mViewCloudFile = true;
                } else {
                    args.mViewCloudFile = false;
                }

                mFragment.stopObserver();

                args.mSrcList = mSrcRecordList;
                args.mDst = dstRecord;

                if (op == Operation.MOVE_TO_PRIVATE) {
                    op = Operation.MOVE;
                }

                FileOperationFragment fg = FileOperationFragment.createInstance(context, mFragment, mFragment.getFragmentManager(), op, args,
                        this);
                if (fg != null) {
                    fg.showAllowingStateLoss(mFragment.getFragmentManager(), "file_operation_dialog");
                }
                break;

            default:
                break;
        }
    }

    private void enterToDst(NavigationManager naviMgr, FileRecord dstRecord) {
        NavigationInfo info = NavigationInfo.getInstance(NavigationMode.Normal, dstRecord);
        NavigationInfo curInfo = naviMgr.getCurInfo();
        if (!info.equals(curInfo)) {
            info.setScreenPath(UiUtils.getScreenPathFromRecord(dstRecord));
            naviMgr.enter(info);
        }
    }

    private void startDestinationSelectorBottomSheet(Operation operation, ArrayList<FileRecord> srcRecordList) {
        mSrcRecordList = srcRecordList;
        Intent intent = new Intent(mActivity, FolderSelectorBottomSheetActivity.class);
        NavigationManager naviMgr = NavigationManager.getInstance(mFragment.getProcessId());
        NavigationInfo curInfo = naviMgr.getCurInfo();
        boolean isFromPrivateStorage = false;
        SamsungAnalyticsLog.ScreenPath currentPath = null;

        if (curInfo != null) {
            if (curInfo.getStorageType() == StorageType.Category || curInfo.getStorageType() == StorageType.Search) {
                isFromPrivateStorage = FileUtils.hasPrivateFile(mSrcRecordList);
            } else {
                isFromPrivateStorage = FileUtils.isPrivateFolder(curInfo.getCurRecord().getFullPath());
            }
            currentPath = curInfo.getScreenPath();
            naviMgr.setFromPrivateStorage(isFromPrivateStorage);
        }
        NavigationInfo startInfo = getStartNavigationInfo(naviMgr, operation);
        String storageType = null;
        String path = null;
        String navigationMode = null;
        if (startInfo != null) {
            storageType = startInfo.getCurRecord().getStorageType().name();
            path = startInfo.getCurRecord().getFullPath();
            navigationMode = startInfo.getNavigationMode().name();
        }
        intent.setAction(Intent.ACTION_MAIN);
        intent.putExtra(FolderSelectorBottomSheetActivity.EXTRA_KEY_FOLDER_SELECTOR_BOTTOM_SHEET, true);
        intent.putExtra(FolderSelectorBottomSheetActivity.EXTRA_KEY_OPERATION, operation.name());
        intent.putExtra(FolderSelectorBottomSheetActivity.EXTRA_KEY_STORAGE_TYPE, storageType);
        intent.putExtra(FolderSelectorBottomSheetActivity.EXTRA_KEY_START_PATH, path);
        intent.putExtra(FolderSelectorBottomSheetActivity.EXTRA_KEY_NAVIGATION_MODE, navigationMode);
        intent.putExtra(FolderSelectorBottomSheetActivity.EXTRA_KEY_FROM_PRIVATE_STORAGE, isFromPrivateStorage);
        intent.putExtra(FolderSelectorBottomSheetActivity.EXTRA_KEY_PREV_SCREEN_PATH, currentPath != null ? currentPath.getCode() : -1);
        if (NavigationMode.Select_optimize_storage_backup_destination.name().equals(navigationMode)) {
            intent.putExtra(FolderSelectorBottomSheetActivity.EXTRA_KEY_TOTAL_COUNT, mFragment.getTotalFileCount());
        }
        mActivity.startActivityForResult(intent,
                FolderSelectorBottomSheetActivity.REQ_CODE_FOLDER_SELECTOR_BOTTOM_SHEET);
    }

    private NavigationInfo getStartNavigationInfo(NavigationManager naviMgr, Operation operation) {
        NavigationInfo info = null;
        FileRecord rootPath;
        if ((naviMgr.isFromPrivateBox() || naviMgr.isFromPrivateStorage())
                && operation != Operation.REMOVE_FROM_PRIVATE) {
            rootPath = FileRecord.createFileRecord(StorageType.Local, AppConstants.StoragePath.PRIVATE_ROOT);
        } else {
            rootPath = FileRecord.createFileRecord(StorageType.Home, "");
        }

        if (operation == Operation.COPY) {
            info = NavigationInfo.getInstance(NavigationMode.Select_copy_destination, rootPath);
        } else if (operation == Operation.MOVE) {
            info = NavigationInfo.getInstance(NavigationMode.Select_move_destination, rootPath);
        } else if (operation == Operation.REMOVE_FROM_PRIVATE) {
            info = NavigationInfo.getInstance(NavigationMode.Select_remove_from_private, rootPath);
        } else if (operation == Operation.BACKUP) {
            info = NavigationInfo.getInstance(NavigationMode.Select_optimize_storage_backup_destination, rootPath);
        }
        return info;
    }

    @Override
    public void onResult(Operation opType, boolean bRet, Bundle extras) {
        // Todo..
        if (mPostOperation != null) {
            mPostOperation.onResult(opType, bRet, extras);
        }

        if (opType != Operation.BACKUP) {
            handleCopyMove(opType, bRet, extras);
        }
        clearSelectedList();
    }

    private void handleCopyMove(Operation opType, boolean bRet, Bundle extras) {
        mFragment.finishActionMode();
        if (AppFeatures.isKnoxDesktopMode()) {
            MouseKeyboardMgr.setCtrlCopy(false);
            MouseKeyboardMgr.setCtrlMove(false);
            MouseKeyboardMgr.notifyItemUpdated();
        }

        if (mProgress == OperationProgress.DOWNLOAD_OPEN) {
            if (bRet) {
                try {
                    FileRecord record = FileRecord.createFileRecord(StorageType.Local, mDstFullPath + "/" + mSrcRecordList.get(0).getName());
                    if (record != null) {
                        FileExecute.openFile(mFragment.getProcessId(), record, mActivity);
                    } else {
                        Log.e(this, "FileRecord is null - " + Log.getEncodedMsg(mDstFullPath));
                    }
                } catch (NullPointerException e) {
                    Log.e(this, "mSrcRecordList is null");
                }
            }
        }

        PrivateModeMgr privateModeMgr = PrivateModeMgr.getInstance(mFragment.getContext());
        privateModeMgr.clearMgr(bRet);

        if (AppFeatures.isTabletUIMode()) {
            int recordType = FileUtils.getRecordType(mSrcRecordList);
            if ((recordType & FileUtils.ITEM_TYPE.FOLDER) != 0) {
                DbTableInfo tableInfo = FolderTreeDbTableInfo.getInstance();
                Uri uri = Uri.parse(tableInfo.getUri());
                String where = new StringBuilder().append(FolderTreeProviderImp.COL_OPEN_PATH_NAME).append(" =? OR ")
                        .append(FolderTreeProviderImp.COL_OPEN_PATH_NAME).append(" like ?").toString();
                if (mSrcRecordList != null && !mSrcRecordList.isEmpty() && mSrcRecordList.get(0) != null && mSrcRecordList.get(0).getParent() != null) {
                    String parentPath = mSrcRecordList.get(0).getParent().getFullPath();
                    String[] args = new String[]{
                            parentPath, parentPath + "/%"};
                    mActivity.getContentResolver().delete(uri, where, args);
                    UiUtils.sendLocalBroadcastIntent(mActivity, AppConstants.MYFILES_ACTION_FOLDER_DELETED, -1);
                }
            }
        }

        if (extras != null) {
            String msgStorageError = extras.getString(FileOperator.POPUP_MSG_BUNDLE, "");
            if (!TextUtils.isEmpty(msgStorageError)) {
                MyFilesFacade.showNotEnoughStorage(mFragment.getProcessId(), mActivity, mActivity.getFragmentManager(), getSelectedList(), msgStorageError, opType);
            }
        }
    }

    public static ArrayList<FileRecord> getSelectedList() {
        return mSrcRecordList;
    }

    public static void clearSelectedList() {
        mSrcRecordList = null;
    }

    private boolean isMovePossible(Context context, FileRecord srcRecord, FileRecord dstRecord) {
        boolean bRet = false;

        if (srcRecord != null && dstRecord != null) {
            String msg = "";
            if (srcRecord.getPath() != null && srcRecord.getPath().equals(dstRecord.getFullPath())) {
                msg = context.getString(R.string.destination_folder_is_same_as_source_folder);
            } else if (srcRecord.isChildDirectory(dstRecord) || srcRecord.getFullPath().equals(dstRecord.getFullPath())) {
                msg = context.getString(R.string.destination_folder_is_subfolder_of_source_folder);
            } else {
                bRet = true;
            }

            if (!bRet) {
                Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
            }
        }

        return bRet;
    }

    public static void setRemoveFromPrivateOperation(boolean moveToPrivate) {
        mRemoveFromPrivateOperation = moveToPrivate;
    }

    public static boolean isRemoveFromPrivateOperation() {
        return mRemoveFromPrivateOperation;
    }
}
